<!DOCTYPE html>
<html lang="zh-CN">

<!-- Head tag -->
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  
  <meta name="baidu-site-verification" content="undefined" />
  <meta name="google-site-verification" content="undefined" />
  <meta name="msvalidate.01" content="undefined" />
  <meta name="360-site-verification" content="undefined" />
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <!-- if page has tags, then add tags to keyword -->
  
  
  <meta name="keywords" content=",基础,tcp/http,">
  <!-- page.description has higher priority -->
  <meta name="description" content="简述HTTPS/SSL/TLS运行过程,不作细节实现的解剖">
  <link rel="shortcut icon" href="/blog/img/logo.webp">
  <title>
    
    简述HTTPS/SSL/TLS运行过程 | Evrn
    
  </title>

  <link rel="canonical" href="/blog/post/tcp-what-is-https.html">
  
<link rel="stylesheet" href="/blog/css/reset.css">

  
<link rel="stylesheet" href="/blog/css/layout.css">

  
<link rel="stylesheet" href="/blog/css/markdown.css">

  <!-- Pygments Highlight CSS -->
  
<link rel="stylesheet" href="/blog/css/highlight.css">

  
<link rel="stylesheet" href="/blog/css/geektutu.css">

  <!-- global function -->
  <script>
    window.globalAddScript = function (url, onload, onerror) {
      var s = document.createElement('script');
      s.src = url;
      onload && (s.onload = onload);
      onerror && (s.onerror = onerror);
      document.body.appendChild(s);
    }
    window.globalAddCss = function (url) {
      var s = document.createElement('link');
      s.rel = 'stylesheet';
      s.href = url;
      document.body.appendChild(s);
    }
    window.getPosition = function (ele) {
      var x = 0, y = 0;
      while (ele) {
        x += (ele.offsetLeft - ele.scrollLeft + ele.clientLeft);
        y += (ele.offsetTop - ele.scrollTop + ele.clientTop);
        ele = ele.offsetParent;
      }
      return { x: x, y: y };
    }
    window.getDom = function (str) { return document.querySelector(str) }
  </script>
  <!-- google ad -->
  
<meta name="generator" content="Hexo 4.2.0"></head>

<body>
    <header class="gkt-header col-xs-12 padding-0">
    <div id="gkt-nav" class="gkt-header-container">
        <a href="/blog/" class="gkt-header-title float-left">
            <img class="float-left" src="/blog/img/logo.webp" alt="">
            <span>Evrn</span>
        </a>
        <nav class="gkt-header-nav text-right">
            <ul>
                <li><a class="hidden-xs" href="/blog/">主页</a></li>
                <li><a href="/blog/series/">专题</a></li>
                <li><a href="/blog/archives/">归档</a></li>
                <li><a href="/blog/post/link.html">友链</a></li>
                <li><a href="/blog/post/about.html">留言</a></li>
            </ul>
        </nav>
    </div>
    <div id="gkt-cate-nav" class="gkt-header-container hidden-xs">
        
        <nav class="gkt-header-nav float-left">
            <ul>
                
                
                <li class="gkt-cate-name float-left ">
                    <a class="float-left" href="/blog/post/go-learn-interface.html">Golang学习</a>
                    
                </li>
                
                <li class="gkt-cate-name float-left ">
                    <a class="float-left" href="/blog/post/go-asm-indroduce.html">Golang汇编</a>
                    
                </li>
                
                <li class="gkt-cate-name float-left active">
                    <a class="float-left" href="/blog/post/tcp-three-way-handshake.html">基础</a>
                    
                </li>
                
                <li class="gkt-cate-name float-left ">
                    <a class="float-left" href="/blog/post/go-how-to-build.html">Golang底层</a>
                    
                </li>
                
                <li class="gkt-cate-name float-left ">
                    <a class="float-left" href="/blog/post/mysql-index-use.html">MySQL</a>
                    
                </li>
                
            </ul>
        </nav>
    </div>
</header>
<div style="height: 44px"></div>
<div class="hidden-xs" style="height: 44px"></div>
<script>
    (function () {
        window.addEventListener('scroll', function () {
            if (window.innerWidth < 768) {
                return;
            }
            var nav = document.querySelector('#gkt-nav');
            var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
            scrollTop > 50 && (nav.classList.add('hide'));
            scrollTop <= 50 && (nav.classList.remove('hide'));
        });
        var cateNavs = document.querySelectorAll('#gkt-cate-nav>nav>ul>li');
        [].slice.call(cateNavs).forEach(function (item) {
            var sub = item.querySelector('.gkt-sub-cate');
            if (!sub) return;
            item.addEventListener('mouseenter', function (e) { sub.style.display = 'block'; }, false);
            item.addEventListener('mouseleave', function (e) { sub.style.display = 'none'; }, false);
        })
    })();
</script>
    <!-- Main Content -->
    <div class="main-container">
        <!-- Main Content -->
<main class="col-xs-12 padding-0 markdown-it">
    <!-- Post Container -->
    
    
    <!-- Post Content -->
<div class="float-left post-container box-shadow">
    <div class="u-arrow-wrapper hidden-xs">
        
        <a class="float-left" href="/blog/post/tcp-three-way-handshake.html"><i class="u-arrow-left"></i></a>
        
        
        <a class="float-right" href="/blog/post/mysql-index-use.html"><i class="u-arrow-right"></i></a>
        
    </div>
    <article class="col-xs-12">
        <h1> 简述HTTPS/SSL/TLS运行过程 </h1>

        

        
        <div class="hidden-lg hidden-md series_links">
            <p> <strong> 基础系列文章链接：</strong></p>
            <ul>
                
                <li>
                    <a href="/blog/post/tcp-three-way-handshake.html">简述TCP“3次握手，4次挥手”</a>
                    <span class="post-item-date">(Feb 21, 2020)</span>
                </li>
                
                <li>
                    <a href="/blog/post/tcp-what-is-https.html">简述HTTPS/SSL/TLS运行过程</a>
                    <span class="post-item-date">(Feb 22, 2020)</span>
                </li>
                
            </ul>
        </div>
        
        
        
        <h2 id="问题"><a href="#问题" class="headerlink" title="问题"></a>问题</h2><p>我们知道普通的http通信采用的是不加密明文传播，很容易受到中间人攻击.</p>
<blockquote>
<p>中间人攻击（MITM攻击）是指，黑客拦截并篡改网络中的通信数据。又分为被动MITM和主动MITM，被动MITM只窃取通信数据而不修改，而主动MITM不但能窃取数据，还会篡改通信数据。最常见的中间人攻击常常发生在公共wifi或者公共路由上。</p>
</blockquote>
<p>由此带来了三大风险</p>
<p>（1） <strong>窃听风险</strong>（eavesdropping）：第三方可以获知通信内容。</p>
<p>（2） <strong>篡改风险</strong>（tampering）：第三方可以修改通信内容。</p>
<p>（3） <strong>冒充风险</strong>（pretending）：第三方可以冒充他人身份参与通信。</p>
<h2 id="解决"><a href="#解决" class="headerlink" title="解决"></a>解决</h2><p>那怎么解决这个问题呢</p>
<p>首先为了防止窃听，我们可以对内容进行加密，双方<strong>约定好一个密钥</strong>，对传输的内容加解密，中间人获取的只是加密的内容，没有密钥无法知道内容，这是常见的<strong>对称加密</strong></p>
<p>问题来了，我怎么给这个密钥给对方呢，如果通过网络传输，那中间人还是能获取到我发送的密钥啊，有没有可能不发这个密钥但是也只有对方才能解密我的内容呢，这就可以用上<strong>非对称加密</strong></p>
<p>所谓非对称加密就是将密钥分成公钥和私钥，公钥顾名思义就是公开的，任何人都可以获取到并用它来加密信息，但是解密<strong>只能通过私钥</strong>来解。</p>
<p>这就好了，我把我的公钥给对方，对方把他的公钥给我，各自的私钥自己藏着，拿到对方的数据后再拿出私钥解密，不就好了？</p>
<p>安全上是没问题，但是由此带来的就是<strong>性能问题</strong>，因为非对称加解密要比对称加解密要慢很多，我们请求一个网页不是一两个连接就能搞定的，可能要十几个连接，全部用非对称加密就太慢了。</p>
<p>那既然十几个链接非对称加密太慢，那我们能不能只送脑袋，哦不，只用非对称加密传输这个密钥，对方安全拿到密钥后还就可以愉快的进行对称加密了。</p>
<p>这时候就轮到SSL/TLS登场了，简单来说它的思路就是</p>
<p>1.通过非对称加密双方交换密钥</p>
<p>2.通过密钥对数据进行对称加密通信</p>
<h2 id="SSL-TLS"><a href="#SSL-TLS" class="headerlink" title="SSL/TLS"></a>SSL/TLS</h2><p>TLS和SSL其实是同一个东西，TLS可以认为是SSL的升级版</p>
<p>目前，应用最广泛的是TLS 1.0，接下来是SSL 3.0。但是，主流浏览器都已经实现了TLS 1.2的支持。</p>
<p>TLS 1.0通常被标示为SSL 3.1，TLS 1.1为SSL 3.2，TLS 1.2为SSL 3.3。</p>
<p>如果想了解这方面具体的实现细节，请参阅<a href="http://tools.ietf.org/html/rfc5246" target="_blank" rel="noopener">RFC文档</a>。</p>
<h3 id="SSL-TLS的作用"><a href="#SSL-TLS的作用" class="headerlink" title="SSL/TLS的作用"></a>SSL/TLS的作用</h3><p>（1） 所有信息都是<strong>加密传播</strong>，第三方无法窃听。</p>
<p>（2） 具有<strong>校验机制</strong>，一旦被篡改，通信双方会立刻发现。</p>
<p>（3） 配备<strong>身份证书</strong>，防止身份被冒充。</p>
<h2 id="握手过程"><a href="#握手过程" class="headerlink" title="握手过程"></a>握手过程</h2><p><img src="http://river.marvelthanos.com/blog/20200309/7AYEjvEhR8Er.png?imageslim" alt="mark"></p>
<p>“握手阶段”涉及四次通信，我们一个个来看。需要注意的是，”握手阶段”的所有通信都是明文的。</p>
<h3 id="1-客户端发出请求（ClientHello）"><a href="#1-客户端发出请求（ClientHello）" class="headerlink" title="1 客户端发出请求（ClientHello）"></a><strong>1 客户端发出请求（ClientHello）</strong></h3><p>首先，客户端（通常是浏览器）先向服务器发出加密通信的请求，这被叫做ClientHello请求。</p>
<p>在这一步，客户端主要向服务器提供以下信息。</p>
<blockquote>
<p>（1） 支持的协议版本，比如TLS 1.0版。</p>
<p>（2） 一个客户端生成的随机数，稍后用于生成”对话密钥”。</p>
<p>（3） 支持的加密方法，比如RSA公钥加密。</p>
<p>（4） 支持的压缩方法。</p>
</blockquote>
<p>这里需要注意的是，客户端发送的信息之中不包括服务器的域名。也就是说，理论上服务器只能包含一个网站，否则会分不清应该向客户端提供哪一个网站的数字证书。这就是为什么通常一台服务器只能有一张数字证书的原因。</p>
<p>对于虚拟主机的用户来说，这当然很不方便。2006年，TLS协议加入了一个<a href="http://tools.ietf.org/html/rfc4366" target="_blank" rel="noopener">Server Name Indication扩展</a>，允许客户端向服务器提供它所请求的域名。</p>
<p><img src="http://river.marvelthanos.com/blog/20200309/Th1pUJXDki5j.png?imageslim" alt="mark"></p>
<h3 id="2-服务器回应（SeverHello）"><a href="#2-服务器回应（SeverHello）" class="headerlink" title="2 服务器回应（SeverHello）"></a><strong>2 服务器回应（SeverHello）</strong></h3><p>服务器收到客户端请求后，向客户端发出回应，这叫做SeverHello。服务器的回应包含以下内容。</p>
<blockquote>
<p>（1） 确认使用的加密通信协议版本，比如TLS 1.0版本。如果浏览器与服务器支持的版本不一致，服务器关闭加密通信。</p>
<p>（2） 一个服务器生成的随机数，稍后用于生成”对话密钥”。</p>
<p>（3） 确认使用的加密方法，比如RSA公钥加密。</p>
<p>（4） 服务器证书。</p>
</blockquote>
<p>除了上面这些信息，如果服务器需要确认客户端的身份，就会再包含一项请求，要求客户端提供”客户端证书”。比如，金融机构往往只允许认证客户连入自己的网络，就会向正式客户提供USB密钥，里面就包含了一张客户端证书。</p>
<h4 id="Server-Hello"><a href="#Server-Hello" class="headerlink" title="Server Hello"></a>Server Hello</h4><p><img src="http://river.marvelthanos.com/blog/20200309/L7tUtfLDOtnT.png?imageslim" alt="mark"></p>
<h4 id="Certificate"><a href="#Certificate" class="headerlink" title="Certificate"></a>Certificate</h4><p><img src="http://river.marvelthanos.com/blog/20200309/0WjOoyDO2aXF.png?imageslim" alt="mark"></p>
<h4 id="Server-Key-Exchange"><a href="#Server-Key-Exchange" class="headerlink" title="Server Key Exchange"></a>Server Key Exchange</h4><p>当 server certificate 没有携带足够的信息时，发送给客户端以计算 pre-master，如基于DH 的证书，公钥不被证书中包含，需要单独发送</p>
<h4 id="Server-Hello-Done"><a href="#Server-Hello-Done" class="headerlink" title="Server Hello Done"></a>Server Hello Done</h4><p>服务器返回此协议数据，告诉客户端已经完成</p>
<p><img src="http://river.marvelthanos.com/blog/20200309/QOmHx9OP5dX5.png?imageslim" alt="mark"></p>
<h3 id="3-客户端回应"><a href="#3-客户端回应" class="headerlink" title="3 客户端回应"></a><strong>3 客户端回应</strong></h3><p>客户端收到服务器回应以后，首先验证服务器证书。如果证书不是可信机构颁布、或者证书中的域名与实际域名不一致、或者证书已经过期，就会向访问者显示一个警告，由其选择是否还要继续通信。</p>
<p>如果证书没有问题，客户端就会从证书中取出服务器的公钥。然后，向服务器发送下面三项信息。</p>
<blockquote>
<p>（1） 一个随机数。该随机数用服务器公钥加密，防止被窃听。</p>
<p>（2） 编码改变通知，表示随后的信息都将用双方商定的加密方法和密钥发送。</p>
<p>（3） 客户端握手结束通知，表示客户端的握手阶段已经结束。这一项同时也是前面发送的所有内容的hash值，用来供服务器校验。</p>
</blockquote>
<p>上面第一项的随机数，是整个握手阶段出现的第三个随机数，又称”pre-master key”。有了它以后，客户端和服务器就同时有了三个随机数，接着双方就用事先商定的加密方法，各自生成本次会话所用的同一把”会话密钥”。</p>
<p>至于为什么一定要用三个随机数，来生成”会话密钥”，<a href="http://blog.csdn.net/dog250/article/details/5717162" target="_blank" rel="noopener">dog250</a>解释得很好：</p>
<blockquote>
<p>“不管是客户端还是服务器，都需要随机数，这样生成的密钥才不会每次都一样。由于SSL协议中证书是静态的，因此十分有必要引入一种随机因素来保证协商出来的密钥的随机性。</p>
<p>对于RSA密钥交换算法来说，pre-master-key本身就是一个随机数，再加上hello消息中的随机，三个随机数通过一个密钥导出器最终导出一个对称密钥。</p>
<p>pre master的存在在于SSL协议不信任每个主机都能产生完全随机的随机数，如果随机数不随机，那么pre master secret就有可能被猜出来，那么仅适用pre master secret作为密钥就不合适了，因此必须引入新的随机因素，那么客户端和服务器加上pre master secret三个随机数一同生成的密钥就不容易被猜出了，一个伪随机可能完全不随机，可是是三个伪随机就<strong>十分接近随机</strong>了，每增加一个自由度，随机性增加的可不是一。”</p>
</blockquote>
<p>此外，如果前一步，服务器要求客户端证书，客户端会在这一步发送证书及相关信息。</p>
<h4 id="Client-Key-Exchange"><a href="#Client-Key-Exchange" class="headerlink" title="Client Key Exchange"></a>Client Key Exchange</h4><p>合法性验证通过之后，客户端计算产生随机数字 Pre-master，并用证书公钥加密，发送给服务器</p>
<h4 id="Change-Cipher-Spec"><a href="#Change-Cipher-Spec" class="headerlink" title="Change Cipher Spec"></a>Change Cipher Spec</h4><p>客户端通知服务器后续的通信都采用协商的通信密钥和加密算法进行加密通信</p>
<p><img src="http://river.marvelthanos.com/blog/20200309/8qqWgFPQQCEs.png?imageslim" alt="mark"></p>
<h3 id="4-服务器的最后回应"><a href="#4-服务器的最后回应" class="headerlink" title="4 服务器的最后回应"></a><strong>4 服务器的最后回应</strong></h3><p>服务器收到客户端的第三个随机数pre-master key之后，计算生成本次会话所用的”会话密钥”。然后，向客户端最后发送下面信息。</p>
<blockquote>
<p>（1）编码改变通知，表示随后的信息都将用双方商定的加密方法和密钥发送。</p>
<p>（2）服务器握手结束通知，表示服务器的握手阶段已经结束。这一项同时也是前面发送的所有内容的hash值，用来供客户端校验。</p>
</blockquote>
<p>至此，整个握手阶段全部结束。接下来，客户端与服务器进入加密通信，就完全是使用普通的HTTP协议，只不过用”<strong>会话密钥</strong>“加密内容。</p>
<h4 id="Encrypted-Handshake-Message"><a href="#Encrypted-Handshake-Message" class="headerlink" title="Encrypted Handshake Message"></a>Encrypted Handshake Message</h4><p>服务器也结合所有当前的通信参数信息生成一段数据并采用协商密钥 session secret 与算法加密并发送到客户端</p>
<h2 id="小结TLS握手："><a href="#小结TLS握手：" class="headerlink" title="小结TLS握手："></a>小结TLS握手：</h2><p>1.客户端自己生成<strong>随机码1</strong>和支持的加密算法(用于密钥加密)给服务端。</p>
<p>2.服务端从客户端支持的<strong>加密算法</strong>中选一个同时生成一个<strong>随机码2</strong>，还有<strong>服务器证书</strong>，一起发送给客户端。</p>
<p>3.客户端收到服务器证书，先验证证书是否可信的机构颁发的证书，证书的来源是否证书上的域名，<strong>防止中间人透明传输</strong>。确认无误后，再生成一个<strong>随机数3</strong>，对这个随机数3用公钥加密，发送给服务端。</p>
<p>4.服务端用私钥解密得到随机码3，此时客户端和服务端同时拥有三个随机码，用之前约定的加密方法生成一个最终的<strong>会话密钥</strong>之后的传输就通过这个会话密钥进行对称加密传输</p>
<p>5.前两个随机码都是明文传输，都可以被中间人截获，关键就是第三个随机码通过非对称加密传输，中间人无法获知，所以最终的会话密钥就能保证安全。</p>
<h2 id="密钥交换算法介绍："><a href="#密钥交换算法介绍：" class="headerlink" title="密钥交换算法介绍："></a>密钥交换算法介绍：</h2><p>密钥交换算法目前常用的有RSA和Diffie-Hellman。<br>对于密钥交换使用RSA算法，pre-master-secret由客户端生成，并使用公钥加密传输给服务器。<br>对于密钥交换使用Diffie-Hellman算法，pre-master-secret则通过在Key Exchange阶段交换的信息，由各自计算出pre-master-secret。</p>
<h2 id="参考资料"><a href="#参考资料" class="headerlink" title="参考资料"></a>参考资料</h2><p><a href="https://blog.csdn.net/xiaoming100001/article/details/81109617" target="_blank" rel="noopener">HTTP和HTTPS协议，看一篇就够了</a></p>
<p><a href="http://www.ruanyifeng.com/blog/2014/09/illustration-ssl.html" target="_blank" rel="noopener">阮一峰图解SSL/TLS协议</a></p>
<p><a href="http://www.ruanyifeng.com/blog/2014/02/ssl_tls.html" target="_blank" rel="noopener">阮一峰SSL/TLS协议运行机制的概述</a></p>
<p><a href="https://blog.helong.info/blog/2015/09/06/tls-protocol-analysis-and-crypto-protocol-design/" target="_blank" rel="noopener">TLS协议分析 与 现代加密通信协议设计</a></p>
<p><a href="http://tools.ietf.org/html/rfc5246" target="_blank" rel="noopener">RFC文档</a></p>
<p><a href="https://blog.csdn.net/weixin_33670429/article/details/91997441" target="_blank" rel="noopener">WireShark抓Https数据流程分析</a></p>

        
<script src="/blog/js/qrious.min.js"></script>


        <hr>
        <div>
            
            <p>
                <span>专题: </span>
                
                <a href="/blog/series/#基础">
                    <code key="基础" class="post-label">基础</code>
                </a>
                
            </p>
            
            <p>
                <span>本文发表于 2020-02-22，最后修改于 2020-03-10。</span>
            </p>
            <!-- 文章末尾的提示 start -->
            
            
            
                
            <!-- 文章末尾的提示 end -->
        </div>
        <hr />
        <p name="pagination" style="font-size: 1.2em">
    
    <a class="float-left" href="/blog/post/tcp-three-way-handshake.html">上一篇 « 简述TCP“3次握手，4次挥手”</a>
    
    
    <a class="float-right" href="/blog/post/mysql-index-use.html">下一篇 » 《高性能MySQL》笔记-索引优化</a>
    
</p>
    </article>
    <!-- 赞赏 -->
    <!--打赏-->

    <!-- 推荐阅读三篇文章 -->
    <div class="col-xs-12">
        <h3>推荐阅读</h3>
        
        <div class="post-preview">
    <div class="post-img" style="background-image: url('/blog/img/database/database.webp')"></div>
    <div class="post-info">
        <div class="post-info-center">
            <div class="hidden-xs">
                
                
                <span>/</span>
                
                <a class="text-gray" href="/blog/tags/#MySQL"
                    title="MySQL">MySQL</a>
                <span>/</span>
                
                
            </div>
            <a href="/blog/post/mysql-index-use.html" class="title">
                《高性能MySQL》笔记-索引优化
            </a>
            <p class="text-gray">
                <small>
                    <span>发表于2020-03-01，</span>
                    <span class="hidden-xs">全文13286字，</span>
                    <span>阅读约45分钟</span>
                </small>
            </p>
        </div>
    </div>
</div>
        
        <div class="post-preview">
    <div class="post-img" style="background-image: url('/blog/img/go.webp')"></div>
    <div class="post-info">
        <div class="post-info-center">
            <div class="hidden-xs">
                
                
                <span>/</span>
                
                <a class="text-gray" href="/blog/tags/#Golang底层"
                    title="Golang底层">Golang底层</a>
                <span>/</span>
                
                <a class="text-gray" href="/blog/tags/#Golang"
                    title="Golang">Golang</a>
                <span>/</span>
                
                
            </div>
            <a href="/blog/post/go-how-to-build.html" class="title">
                Golang程序编译执行流程
            </a>
            <p class="text-gray">
                <small>
                    <span>发表于2020-03-01，</span>
                    <span class="hidden-xs">全文7487字，</span>
                    <span>阅读约25分钟</span>
                </small>
            </p>
        </div>
    </div>
</div>
        
        <div class="post-preview">
    <div class="post-img" style="background-image: url('/blog/img/goasm/3.webp')"></div>
    <div class="post-info">
        <div class="post-info-center">
            <div class="hidden-xs">
                
                
                <span>/</span>
                
                <a class="text-gray" href="/blog/tags/#Golang汇编"
                    title="Golang汇编">Golang汇编</a>
                <span>/</span>
                
                <a class="text-gray" href="/blog/tags/#Golang底层"
                    title="Golang底层">Golang底层</a>
                <span>/</span>
                
                <a class="text-gray" href="/blog/tags/#Golang"
                    title="Golang">Golang</a>
                <span>/</span>
                
                
            </div>
            <a href="/blog/post/go-asm-my-asm.html" class="title">
                Golang汇编(三)-编写自己的汇编代码
            </a>
            <p class="text-gray">
                <small>
                    <span>发表于2020-02-19，</span>
                    <span class="hidden-xs">全文8065字，</span>
                    <span>阅读约27分钟</span>
                </small>
            </p>
        </div>
    </div>
</div>
        
    </div>
    <div class="col-xs-12">
        <!-- 标签列表 -->
        <!-- Featured Tags -->
<style>
    #featured-tag .post-tag-item {
        font-size: 12px;
        line-height: 30px;
        display: inline-block;
        height: 30px;
        margin: 5px 0px;
        padding: 0 7px;
        color: #333;
        border-radius: 15px;
        background: #f6f6f6;
    }

    #featured-tag .post-tag-item:hover {
        color: #337ab7;
    }
</style>
<div id="featured-tag">
    
    <a class="post-tag-item" href="/blog/tags/#关于我" title="关于我"
        rel="1">#关于我 (1) </a>
    
    <a class="post-tag-item" href="/blog/tags/#友链" title="友链"
        rel="1">#友链 (1) </a>
    
    <a class="post-tag-item" href="/blog/tags/#Golang汇编" title="Golang汇编"
        rel="4">#Golang汇编 (4) </a>
    
    <a class="post-tag-item" href="/blog/tags/#Golang底层" title="Golang底层"
        rel="5">#Golang底层 (5) </a>
    
    <a class="post-tag-item" href="/blog/tags/#Golang" title="Golang"
        rel="8">#Golang (8) </a>
    
    <a class="post-tag-item" href="/blog/tags/#Golang基础" title="Golang基础"
        rel="1">#Golang基础 (1) </a>
    
    <a class="post-tag-item" href="/blog/tags/#Golang源码" title="Golang源码"
        rel="2">#Golang源码 (2) </a>
    
    <a class="post-tag-item" href="/blog/tags/#基础" title="基础"
        rel="2">#基础 (2) </a>
    
    <a class="post-tag-item" href="/blog/tags/#tcp/http" title="tcp/http"
        rel="2">#tcp/http (2) </a>
    
    <a class="post-tag-item" href="/blog/tags/#MySQL" title="MySQL"
        rel="3">#MySQL (3) </a>
    
    <a class="post-tag-item" href="/blog/tags/#MySQL优化" title="MySQL优化"
        rel="1">#MySQL优化 (1) </a>
    
</div>
    </div>
    <!-- 评论 -->
    <div class="col-xs-12">
        
    </div>
</div>
<aside class="float-left gkt-sidebar hidden-xs hidden-sm">
    <div style="clear: both"></div>
    <div class="gkt-sidebar-wrapper">
        <section class="box-shadow"><style>
    .gkt-summary {
        border: 1px solid #DDDDDD;
        border-radius: 3px;
        padding: 5px;
        width: 100%;
    }


    .gkt-summary nav {
        overflow: hidden;
    }

    .gkt-summary nav a {
        display: inline-block;
        text-align: center;
        color: #333;
        font-size: 12px;
    }

    .gkt-summary nav span {
        display: block;
    }

    .gkt-summary nav .middle {
        border-left: 1px solid #eaecef;
        border-right: 1px solid #eaecef;
    }

    .gkt-summary .number {
        font-weight: bold;
    }

    .gkt-summary .link-list {
        margin-top: 5px;
        margin-bottom: -5px;
        padding-top: 7px;
        border-top: 1px dashed #999;
        display: flex;
    }

    .gkt-summary .link-list a {
        flex: 1;
    }

    .gkt-summary .link-list img {
        width: 25px;
        height: 25px;
    }
</style>

<div class="gkt-summary">
    <nav>
        <a href="/blog/" class="col-xs-4">
            <number class="number">15</number><span>文章</span>
        </a>
        <a href="/blog/series" class="col-xs-4 middle">
            <number class="number">5</number><span>专题</span>
        </a>
        <a href="/blog/tags" class="col-xs-4">
            <number class="number">11</number><span>标签</span>
        </a>
    </nav>

    
    <div class="link-list">
        
        <a href="https://marvelthanos.com" target="_blank" rel="noopener"><img src="/blog/img/related_links/thanos.webp" /></a>
        
    </div>
    
</div></section>
        
        
        <section class="gkt-sidebar-content box-shadow">
            <strong>基础</strong>
            <ul>
                
                <li>
                    <a href="/blog/post/tcp-three-way-handshake.html"
                        class="">简述TCP“3次握手，4次挥手”</a>
                    
                </li>
                
                <li>
                    <a href="/blog/post/tcp-what-is-https.html"
                        class="gkt-sidebar-active">简述HTTPS/SSL/TLS运行过程</a>
                    
                    <!-- Table of Contents -->
<div id="sidebar-toc">
  <!-- TOC  -->
  
  <ol class="toc-nav"><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#问题"><span class="toc-nav-text">问题</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#解决"><span class="toc-nav-text">解决</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#SSL-TLS"><span class="toc-nav-text">SSL&#x2F;TLS</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#握手过程"><span class="toc-nav-text">握手过程</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#小结TLS握手："><span class="toc-nav-text">小结TLS握手：</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#密钥交换算法介绍："><span class="toc-nav-text">密钥交换算法介绍：</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#参考资料"><span class="toc-nav-text">参考资料</span></a></li></ol>
  
</div>

<script>
  (function () {
    var h2 = document.querySelectorAll('article h2');
    var h3 = document.querySelectorAll('article h3');
    var linkList = document.querySelectorAll('#sidebar-toc a');

    function findLinkElement(name) {
      for (var i = 0; i < linkList.length; i++) {
        var items = linkList[i].href.split('#');
        if (items && items[items.length - 1] === encodeURIComponent(name)) {
          return i;
        }
      }
      return -1;
    }

    function activeLink(titleList) {
      var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
      for (var i = titleList.length - 1; i >= 0; i--) {
        if (scrollTop - titleList[i].offsetTop > 0) {
          var index = findLinkElement(titleList[i].id);
          index != -1 && linkList[index].classList.add('gkt-sidebar-active');
          break;
        }
      }
    }

    window.addEventListener("scroll", function (e) {
      [].slice.call(linkList).forEach(function (link) {
        link.classList.remove('gkt-sidebar-active');
      })
      activeLink(h2);
    })
  })();
</script>
                    
                </li>
                
            </ul>
        </section>
        
        
        <section class="box-shadow">
            <strong>最近的文章</strong>
            <ul>
                
                <li>
                    <a href="/blog/post/go-learn-lib-sorts.html">Go源码学习 sort包</a>
                </li>
                
                <li>
                    <a href="/blog/post/mysql-optimize-explain.html">EXPLAIN-执行计划查询命令</a>
                </li>
                
                <li>
                    <a href="/blog/post/mysql-index-base.html">《高性能MySQL》笔记-索引基础</a>
                </li>
                
            </ul>
        </section>
        <section class="box-shadow text-center">
            
        </section>
    </div>
</aside>

<script>
    (function () {
        var ele = getDom('.gkt-sidebar-content')
        var wrapper = getDom('.gkt-sidebar-wrapper')
        var last = 0
        window.addEventListener("scroll", function (e) {
            var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
            var isDown = scrollTop > last;
            var pos = getPosition(ele).y - scrollTop;
            var downLimit = 50;
            var upLimit = -100;
            // uarrow.style.marginTop = scrollTop + 'px';
            isDown && pos <= downLimit && wrapper.classList.add("gkt-sidebar-fixed");
            !isDown && pos > upLimit && wrapper.classList.remove("gkt-sidebar-fixed");
            last = scrollTop
        })
    })();
    (function () {
        function resizeUArrow() {
            var s = getDom('.u-arrow-wrapper').style
            var pc = getDom('.post-container')
            s.left = getPosition(pc).x + 'px';
            s.width = pc.clientWidth + 'px';
        }
        resizeUArrow()
        window.addEventListener('resize', resizeUArrow);
    })();
</script>

    
</main>
    </div>
    <style>
    img#go-top {
        position: fixed;
        bottom: 100px;
        width: 50px;
        cursor: pointer;
        z-index: 9999;
    }
</style>
<img id="go-top" src="/blog/icon/top.png" class="hidden-xs" style="display: none" />
<script>
    (function () {
        var goTop = document.getElementById('go-top');
        var mainContainer = document.querySelector('.main-container');
        
        goTop.addEventListener('click', function () {
            window.scroll(0, 0);
        }, false);
        window.addEventListener('scroll', function () {
            var right = document.body.offsetWidth - mainContainer.getBoundingClientRect().right;
            var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
            goTop.style.right = right + 10 + 'px'
            scrollTop > 700 && (goTop.style.display = "block");
            scrollTop <= 700 && (goTop.style.display = "none");
        });
    })();
</script>
    <style>
    #geektutu-click-img-container {
        position: fixed;
        left: 0;
        top: 0;
        text-align: center;
        width: 100%;
        display: none;
        z-index: 9999;
    }

    #geektutu-click-img-container img {
        object-fit: contain;
        background: #eaecef;
        padding: 15px;
        border-radius: 10px;
        height: auto;
        width: auto;
        vertical-align: middle;
    }
</style>


<div id="geektutu-click-img-container">
    <img src="" alt="Big Image">
</div>

<script>
    (function () {
        var container = document.querySelector('#geektutu-click-img-container')
        var targetImg = container.querySelector('img')
        var imgs = document.querySelectorAll('article img');
        targetImg.addEventListener('click', function (e) {
            container.style.display = 'none';
            e && e.stopPropagation && e.stopPropagation();
        }, false);

        for (var i = 0; i < imgs.length; ++i) {
            var img = imgs[i];
            img.addEventListener('click', (function (src, rate) {
                return function (e) {
                    e && e.stopPropagation && e.stopPropagation();
                    if (window.innerWidth < 980) {
                        return
                    }
                    targetImg.style.height = targetImg.style.width = 'auto';
                    if (window.innerWidth / window.innerHeight > rate) {
                        targetImg.style.height = (window.innerHeight - 20) + 'px';
                    } else {
                        targetImg.style.width = (window.innerWidth - 20) + 'px';
                    }
                    container.style.height = window.innerHeight + 'px'
                    container.style.lineHeight = window.innerHeight + 'px'
                    container.style.display = 'block';
                    targetImg.src = src;
                };
            }(img.src, img.width / img.height)), false)
        }
    })();
</script>
    <!-- Footer -->
    <!-- Footer -->
<style>
    footer {
        width: 100%;
        line-height: 1.5;
        padding: 20px;
    }

    footer a {
        color: #333;
        text-decoration: none;
    }

    .footer-hexo img {
        height: 20px;
        margin-bottom: -5px;
    }

    .footer-hexo a {
        color: #337ab7;
    }
</style>
<footer class="text-center col-xs-12">
    <p>
        <small>© 2020 - Evrn - </small>
        <small>
            <a target="_blank" rel="nofollow noopener" href="http://www.miitbeian.gov.cn/"></a>
        </small>
    </p>
    <p class="footer-hexo">
        <!-- 但若直接使用或修改主题，请务必保留这段声明 -->
        <small>Powered by <a target="_blank" href="https://hexo.io">Hexo</a> | Theme
            <a target="_blank" href="https://geektutu.com">Geektutu</a>
            <a href="https://github.com/geektutu/hexo-theme-geektutu" target="_blank" rel="noopener">
                <img src=""
                    alt="Github Star">
            </a>
        </small>
    </p>
    
    <p>
        <small>
            <span id="busuanzi_container_site_pv">👁<span id="busuanzi_value_site_pv"></span></span> &nbsp;
            <span id="busuanzi_container_page_pv">📚<span id="busuanzi_value_page_pv"></span></span>
        </small>
    </p>
    
    

</footer>


<script>
    window.addEventListener('load', function () {
        globalAddScript('//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js');
    })
</script>

<!-- Baidu Tongji -->





    <script>
        // 非本站网址，新开tab页签
        (function () {
            var stopBubble = function (e) {
                e && e.stopPropagation && e.stopPropagation();
            }
            var links = document.querySelectorAll('a');
            [].slice.call(links).forEach(function (item) {
                if (item.href && item.href.indexOf(window.location.host) === -1) {
                    item.target = '_blank'
                }
                // 阻止冒泡，不触发彩蛋。
                item.addEventListener('click', stopBubble, false);
            });
            var article = document.querySelector('article');
            article && article.addEventListener('click', stopBubble, false)
        })();
    </script>
    
</body>

</html>